﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MessageServer.threadpool;
using System.Threading;

namespace MessageServer.utilities
{
    public delegate void ExecuteMe();

    interface Executor
    {
        void execute(ExecuteMe runnable);
        void execute(ExecuteMe runnable, MSThreadPoolCallback cb);
        void execute(ExecuteMe runnable, MSThreadPoolCallback cb, ExceptionCallback ecb);
        void waitToComplete();
    }

    class SynchronousExecutor : Executor
    {
        public SynchronousExecutor()
        {
        }

        public void execute(ExecuteMe runnable)
        {
            execute(runnable, null);
        }

        public void execute(ExecuteMe runnable, MSThreadPoolCallback cb, ExceptionCallback ecb)
        {
            try
            {
                runnable();
                if (cb != null) cb(null);
            }
            catch (Exception e)
            {
                //fire off an exception to be handled
                UtilityLogger.LOG.LogError(e, e.Message);
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
                if (ecb != null) ecb(null, e);
            }
        }

        public void execute(ExecuteMe runnable, MSThreadPoolCallback cb)
        {
            execute(runnable, cb, null);
        }

        public void waitToComplete()
        {
        }
    }

    class AsynchronousExecutor : Executor
    {
        Thread _runningThread;

        public AsynchronousExecutor()
        {
        }

        public AsynchronousExecutor(ExecuteMe runnable)
        {
            _runningThread = new Thread(new ThreadStart(runnable));
        }

        public void execute(ExecuteMe runnable)
        {
            //for now ignoring the runnable here to check if performance improves
            if (_runningThread == null)
                _runningThread = new Thread(new ThreadStart(runnable));
            _runningThread.Start();
        }

        public void execute(ExecuteMe runnable, MSThreadPoolCallback cb)
        {
            throw new NotImplementedException();
        }

        public void execute(ExecuteMe runnable, MSThreadPoolCallback cb, ExceptionCallback ecb)
        {
            throw new NotImplementedException();
        }

        public void waitToComplete()
        {
            _runningThread.Join();
        }
    }

    class ExecutorTask : IGatedTask
    {
        ExecuteMe _task;

        public ExecutorTask(ExecuteMe task)
        {
            _task = task;
        }

        public object runTask()
        {
            //let the thread pool handle the exception
            //try
            //{
                _task();
            //}
            //catch (Exception e)
            //{
                //fireoff exception to be handled
            //    UtilityLogger.LOG.LogError(e, e.Message);
            //    Console.WriteLine(e.Message);
            //    Console.WriteLine(e.StackTrace);
            //}
            return null;
        }
    }

    class ThreadPoolExecutor : Executor
    {
        MSThreadPool _pool;

        public ThreadPoolExecutor(String grpname, int wait, int min, int max)
        {
            _pool = new MSThreadPool(grpname, wait, min, max);
        }

        public void execute(ExecuteMe runnable)
        {
            _pool.schedule(new ExecutorTask(runnable));
        }

        public void execute(ExecuteMe runnable, MSThreadPoolCallback cb)
        {
            _pool.schedule(new ExecutorTask(runnable), cb);
        }

        public void execute(ExecuteMe runnable, MSThreadPoolCallback cb, ExceptionCallback ecb)
        {
            _pool.schedule(new ExecutorTask(runnable), cb, ecb);
        }

        public void waitToComplete()
        {
            _pool.Dispose(); //TODO: shd this change??
        }
    }
}
